\documentclass[12pt]{article}
\usepackage{xeCJK}
\usepackage{CJKutf8}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{indentfirst}
\usepackage{listings}
\pagenumbering{gobble}
\usepackage{color}
\usepackage[
  colorlinks=true,
  linkcolor=blue,
  urlcolor=cyan,
]{hyperref}
\usepackage[
  b5paper,
  landscape,
  nohead,
  margin=2cm
]{geometry}

\definecolor{light-gray}{gray}{0.95}
\definecolor{codegreen}{rgb}{0,0.6,0}
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
\definecolor{codepurple}{rgb}{0.58,0,0.82}
\lstset{numbers=right,
  backgroundcolor=\color{light-gray},
  commentstyle=\color{codegreen},
  keywordstyle=\color{magenta},
  stringstyle=\color{codepurple},
  numberstyle=\tiny\color{codegray},
  numberstyle=\footnotesize,
  breaklines=true,
  xleftmargin=\parindent,
  tabsize=2,
  numbersep=5pt
}

\pagestyle{empty}
\setlength{\parskip}{1em}
\hypersetup{pageanchor=false}

\begin{document}

\title{BCID 适合用什么语言来实现}
\date{\today}
\author{ldcc}
\maketitle

\section{RPC 与网络透明性}

\section{分布式算法}

一个分布式系统应分为两个层次，底层负责网络和消息传递，而上层处理消息的到达，以及需要处理的各种请求，而这个上层就是所谓的分布式状态机。
对于一个区块链应用而言，分布式状态机可以简单地概括为 \textbf{分布式的去中心化节点 + 确定有限状态自动机}。
因为分布式状态机的存在，局部性故障可以通过设计来解决。

\section{内存管理}

对于区块链应用的开发者而言，高效的资源管理与内存分配也是需要被考虑到的一点，而内存管理又尤其重要。
下面就现阶段最热门的两种区块链语言 C++ 和 Golang 来做一些比较：

C++ 拥有完全手动的内存管理方式，Golang 有垃圾回收（GC）机制。

一方面 GC 大大减轻了程序员的头脑负担和程序出错的机会，所以从开发友好度角度来说 Ethereum 对于 Bitcoin 是一个进步；
另一方面 Golang 的垃圾回收器是一个非常原始的 Mark-and-Sweep（MS GC 基本上就是扫一下整个堆栈然后将无法获取的资源释放）。
这比起像 Java，OCaml 和 Chez Scheme 之类的语言实现，Golang 的 GC 其实还处于起步阶段。
但在分布式系统的开发中，事无巨细手动去管理每一块内存是非常降低生产率的事情。

\section{语言级支持}

分布式系统的开发策率，一般而言先在本地采用线程来模拟不同的节点，每个线程运行分布式状态机的一个部分，之后才使用真正的节点来取代线程。
关于线程（Thread）本身也有很多种选择，但协程（Coroutine）更适合，因为协程允许对并发行为有更细粒度的控制。

结合\textbf{“C 代码并不会使网络变得更快”}的论点，最适合的开发语言可以转移到能够在语言级支持这种细粒度并发控制的编程语言中去。
虽然这些编程语言往往都是函数式的，比如：

\begin{itemize}
  \item Erlang
  \item Haskell
  \item Kotlin
  \item Clojure
  \item Scheme
  \item Rust
  \item Golang（这里只有 Golang 不是函数式语言）
\end{itemize}

本质上 Coroutine 就是一个调用栈，在一些像 Scheme 的语言中通常叫作 Continuation，到了 Golang 以后一般又被认知为 Goroutine。

Coroutine 或者 Goroutine 其实就是些用户级的 Continuation，系统级的 Continuation 通常被叫做“线程”。

Node.js 那种 “Callback 地狱”，其实就是函数式语言里面常用的一种手法，叫做 Continuation Passing Style (CPS)。
由于 Scheme 有 call/cc，所以从理论上讲，它可以不通过 CPS 样式的代码而实现大并发。
所以函数式语言只要支持 Continuation，就会很容易的实现大并发。

\section{后续维护}

一个分布式系统除了网络因素，有时候也会出现一些莫名其妙的问题，它们大多数是由\textbf{一系列不幸的事件序列所造成的}。
要解决这类问题，大多数时候只能构建一个测试用例，然后让它跑上无数次大量的测试和模拟，以此来重现这极小的失败概率。
这不但会使解决 bug 的过程变的缓慢，你同时还需要花费大量的时间来编写测试（比如以太坊里面那一堆测试）。

\section{纯函数式状态机}

分布式编程最让人难受的一点就是：系统的并发模型往往会成为代码库中的病毒。
当实现了一个有细粒度的并发控制时，代码里到处的并发导致了不确定性，最后不确定性造成了麻烦。
然而分布式节点不能抛弃并发，这时就需要将并发和分布式状态机分离在一起。换句话说，分布式状态机需要成为纯函数式。

\section{讨论？}

\end{document}
